package com.infore.qualityControl.select;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.infore.qualityControl.constant.Constants;
import com.infore.qualityControl.enums.ResultStatus;
import com.infore.qualityControl.select.dto.QueryParamDto;
import com.infore.qualityControl.select.util.QueryCondition;
import com.infore.qualityControl.select.util.QueryUtil;
import com.infore.qualityControl.util.Page;
import com.infore.qualityControl.util.ResultEntity;

@Component
public class QueryDispatcher {

    @Autowired
    EntityManager entityManager;

    /**
     * 查询分发器，入口
     * 
     * @param entityManager
     */
    public ResultEntity dispatcher(QueryParamDto queryParamDto, Class<?> clz) {
        // 根据所传的查询条件内容是否为空重新构造所传参数
        // 重新构造查询条件
        if (queryParamDto.getQueryCondition() != null && queryParamDto.getAssembleCondition() != null) {
            QueryCondition queryCondition = queryParamDto.getQueryCondition();
            List<String> property = queryCondition.getProperty(); // 属性集合
            List<String> operator = queryCondition.getOperator(); // 属性的操作符集合
            List<String> content = queryCondition.getContent(); // 属性的对应匹配内容
            List<String> newProperty = new ArrayList<String>(); // 新的属性集合
            List<String> newOperator = new ArrayList<String>(); // 新的属性操作符集合
            List<String> newContent = new ArrayList<String>(); // 新的属性对应匹配内容集合
            // 判断将参数有特定值的重新加入到指定的新的集合中
            for (int i = 0; i < content.size(); i++) {
                if (StringUtils.isNotBlank(content.get(i).toString())) {
                    newContent.add(content.get(i).toString());
                    newOperator.add(operator.get(i).toString());
                    newProperty.add(property.get(i).toString());
                }
            }
            List<String> assembleCondition = queryParamDto.getAssembleCondition();
            // 清空组装条件
            assembleCondition.clear();
            int contentSum = newContent.size();
            int operatorSum = newOperator.size();
            int propertySum = newProperty.size();
            // 如果查询条件都为空,则重置查询条件与组装条件为null
            if (contentSum == 0 && operatorSum == 0 && propertySum == 0) {
                queryParamDto.setQueryCondition(null);
                queryParamDto.setAssembleCondition(null);
            } else {
                // 根据查询条件重新组装sql配置条件
                if (contentSum == 1) { // 只有一个查询条件时，组装条件为[0]
                    assembleCondition.add((contentSum - 1) + "");
                } else { // 否则依次匹配,列如：["0 and 1","_0 and 2"]
                    for (int i = 0; i < contentSum - 1; i++) {
                        if (i == 0) {
                            assembleCondition.add(i + " and " + (i + 1));
                        } else {
                            assembleCondition.add("_" + (assembleCondition.size() - 1) + " and " + (i + 1));
                        }
                    }
                }
                // 重新set
                queryCondition.setContent(newContent);
                queryCondition.setOperator(newOperator);
                queryCondition.setProperty(newProperty);
                queryParamDto.setQueryCondition(queryCondition);
                queryParamDto.setAssembleCondition(assembleCondition);
            }
        }
        // 构建查询对象
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();// 用于构建CriteriaQuery和构建和组装查询条件
        CriteriaQuery<Tuple> query = criteriaBuilder.createTupleQuery();// 用于组装查询实体
        Root<?> root = query.from(clz);// 包装对象，用于获取被包装对象的属性
        // 构建查询条件
        List<Predicate> predicates = QueryUtil.createQueryCondition(queryParamDto, criteriaBuilder, root);
        // 组装查询条件
        Predicate predicate = QueryUtil.assembleCondition(queryParamDto, criteriaBuilder, predicates);
        // 组装SQL
        QueryUtil.assembleSql(queryParamDto, criteriaBuilder, query, root, predicate);
        // 获取查询结果
        TypedQuery<Tuple> typedQuery = entityManager.createQuery(query);
        List<?> result = typedQuery.getResultList();
        // 获取分页结果
        Page<Map<String, Object>> page = new Page<>();
        result = QueryUtil.getPage(result.size(), result, typedQuery, queryParamDto, page);
        // 封装查询结果
        List<Map<String, Object>> list = new ArrayList<>(); // 结果集
        List<String> selects = Arrays.asList(queryParamDto.getAssembleSql().getSelect().split(","));
        for (Object tuple : result) {
            Map<String, Object> map = new HashMap<>();
            for (int i = 0; i < selects.size(); i++) {
                String filed = selects.get(i).toString();
                if (filed.contains(".")) { // 将数据点对象等形式改成下划线形式,以便前端方便解析
                    filed = filed.replace(".", "_");
                }
                Object object = ((Tuple) tuple).get(i);
                // 判断是否为时间类型,将其转换为字符串
                if (object.getClass().equals(Timestamp.class)) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    map.put(filed, sdf.format(object));
                } else {
                    map.put(filed, object);
                }
            }
            list.add(map);
        }
        if (queryParamDto.getPageObject() != null) {
            page.setList(list);
            return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setPage(page);
        } else {
            return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(list);
        }
    }
}
